home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_11_08 / weber / display.c < prev    next >
Text File  |  1993-03-11  |  32KB  |  794 lines

  1. /***************************************************************
  2.  * file: DISPLAY.C
  3.  * purpose: display a PCX file
  4.  * contains:
  5.  *  display_file() - displays a file.
  6.  *  display_sample() -  gets a pointer to a sample of the displayed file.
  7.  * copyright: 1993 by David Weber.  All rights reserved.
  8.  *  This software can be used for any purpose as object, library or executable.
  9.  *  It cannot be sold for profit as source code.
  10.  * history:
  11.  *  02-26-93 - initial code, cobbled from various stuff
  12.  **************************************************************/
  13.  
  14. #include <stdio.h>
  15. #include <io.h>
  16. #include <fcntl.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include "gui.h"
  20. #include "display.h"
  21. #include "zone.h"
  22.  
  23. /* local prototypes */
  24. static int get_pcx_header(int fh);
  25. static unsigned int read_pcx(unsigned char *buffer,unsigned int number_of_bytes);
  26. static unsigned int read_source_buffer(void);
  27. static int open_scaler(int xscale,int yscale,DISPLAY_BOX *screen,DISPLAY_BOX *file);
  28. static int scaler(unsigned char *buffer);
  29. static void close_scaler(void);
  30. static int open_sampler(DISPLAY_BOX *file);
  31. static void get_sample(unsigned char *scaler_buffer,int ylines);
  32.  
  33. /* local data */
  34.                     /* PCX */
  35. static int src_fh;                      /* file handle of source */
  36. static unsigned int bytes_per_line;     /* byte width of image */
  37. static unsigned int lines_per_page;     /* pixel length of image */
  38. static unsigned int src_bytes;          /* byte count in buffer */
  39. static unsigned int src_size;           /* size of buffer */
  40. static unsigned char *src_buffer;       /* buffer pointer */
  41.                     /* SCALER */
  42. static unsigned char *scaler_buffer;    /* buffer for scaler operations */
  43. static int scaler_in_bytes_per_line;    /* input bytes per line */
  44. static int scaler_out_bytes_per_line;   /* output bytes per line */
  45. static int scaler_error;                /* scaler y error */
  46. static int scaler_delta;                /* scale ratio delat error */
  47. static unsigned int scaler_buffer_size; /* minimum buffer size */
  48. static int scaler_lines;                /* minimum lines in buffer */
  49. static short *scaler_offset;            /* offset from line start for scaler_mask */
  50. static unsigned short *scaler_mask;     /* bit mask of input line */
  51. static int scaler_xscale;               /* x scale value in fixed point .00 */
  52. static int scaler_yscale;               /* y scale value in fixed point .00 */
  53.                     /* DISPLAY */
  54. static unsigned char *display_buffers[MAX_DISPLAY_BUFFERS]; /* array of buffers for display */
  55. static int display_buffer_count = 0;    /* number of allocated buffers */
  56. static int display_lines_per_buffer;    /* number of lines in a buffer */
  57. static int display_bytes_per_line;      /* number of bytes in a display_buffer line */
  58. static DISPLAY_BOX display_screen_box;  /* screen info */
  59. static NUMBERED_BOX *numbered_boxes = NULL; /* numbered boxes outside of image */
  60.                     /* IMAGE SAMPLING */
  61. static int xsample,ysample,xdelta,ydelta;           /* scaled image dimensions */
  62. static int sample_line;                             /* current sample line */
  63. static unsigned char *display_sample_ptr = NULL;    /* pointer to sampled image */
  64.  
  65. /************************************************
  66.  * function: int display_file(char *filename)
  67.  *  Opens PCX file and displays same, displays error box
  68.  *  if it fails
  69.  * parameters: pointer to file name
  70.  * returns: 1 if done or 0 if failed
  71.  ************************************************/
  72. int display_file(char *filename)
  73.     {
  74.     fg_box_t box;
  75.     DISPLAY_BOX screen;
  76.     int screen_aspect_ratio;
  77.     DISPLAY_BOX file;
  78.     int file_aspect_ratio;
  79.     int xscale,yscale,i,skip_it;
  80.     unsigned char *p;
  81.  
  82.     if (display_buffer_count > 0)
  83.         {                   /* clear out previous buffers */
  84.         for (i = 0 ; i < display_buffer_count ; i++)
  85.             free(display_buffers[i]);
  86.         display_buffer_count = 0;
  87.         }
  88.     if (display_sample_ptr != NULL)
  89.         free(display_sample_ptr);
  90.     screen.x = 0;           /* size the display area on screen */
  91.     screen.y = 0;
  92.     screen.width = gui_screen_width;
  93.     screen.height = gui_screen_height - 2 * gui_char_height;
  94.     fg_make_box(box,0,0,screen.width-1,screen.height-1);    /* clear screen */
  95.     fg_msm_hidecursor();
  96.     fg_fillbox(FG_BLACK,FG_MODE_SET,~0,box);
  97.     fg_msm_showcursor();
  98.     if ((src_buffer = (unsigned char *) malloc(PCX_READ_BUFFER)) == NULL)
  99.         {                   /* file read buffer */
  100.         message_box("Out of memory.");
  101.         return 0;
  102.         }
  103.     if ((src_fh = open(filename,O_RDONLY | O_BINARY)) == -1)        /* open file */
  104.         {
  105.         message_box("Cannot open file.");
  106.         free(src_buffer);
  107.         return 0;
  108.         }
  109.     if (!get_pcx_header(src_fh))                    /* decode header */
  110.         {
  111.         message_box("Not a valid monochrome PCX file.");
  112.         free(src_buffer);
  113.         close(src_fh);
  114.         return 0;
  115.         }                   /* the following calculations are fixed point .00 */
  116.     screen_aspect_ratio = (int) (((long)gui_screen_width * 100L) / (long)gui_screen_height);
  117.     file.x = file.y = 0;    /* display area of file */
  118.     file.width = bytes_per_line * 8;
  119.     file.height = lines_per_page;
  120.     file_aspect_ratio = (int) (((long)file.width * 100L) / (long)file.height);
  121.     if (file.width < screen.width || file.height < screen.height)
  122.         {   /* if it has to be scaled up, it has too little info for region finding */
  123.         message_box("PCX file too small for region finding.");
  124.         free(src_buffer);
  125.         close(src_fh);
  126.         return 0;
  127.         }
  128.     if (IDEAL_SCREEN_ASPECT > file_aspect_ratio)
  129.         {   /* y major scaling */
  130.         yscale = (int) (((long)file.height * 100L) / (long)screen.height);
  131.         xscale = (int) (((long)yscale * (long)IDEAL_SCREEN_ASPECT) / (long)screen_aspect_ratio);
  132.         screen.width = (int) (((long)file.width * 100L) / (long)xscale);
  133.         screen.x = (gui_screen_width - screen.width) / 2;
  134.         }
  135.     else
  136.         {   /* x major scaling */
  137.         xscale = (int) (((long)file.width * 100L) / (long)screen.width);
  138.         yscale = (int) (((long)xscale * (long)screen_aspect_ratio) / (long)IDEAL_SCREEN_ASPECT);
  139.         screen.height = (int) (((long)file.height * 100L) / (long)yscale);
  140.         screen.y = (gui_screen_height - 2 * gui_char_height - screen.height) / 2;
  141.         }
  142.     src_bytes = src_size = 0;
  143.     if (!open_scaler(xscale,yscale,&screen,&file))      /* set up scaler */
  144.         {
  145.         free(src_buffer);
  146.         close(src_fh);
  147.         message_box("Out of memory.");
  148.         return 0;
  149.         }
  150.     display_screen_box = screen;                /* set up display parameters */
  151.     display_bytes_per_line = scaler_out_bytes_per_line;
  152.     display_screen_box.width = display_bytes_per_line * 8;
  153.     display_lines_per_buffer = DISPLAY_BUFFER_SIZE / display_bytes_per_line;
  154.     fg_make_box(box,screen.x,screen.y,screen.x+screen.width-1,screen.y+screen.height-1);
  155.     fg_msm_hidecursor();
  156.     fg_fillbox(FG_WHITE,FG_MODE_SET,~0,box);    /* draw blank page */
  157.     fg_make_box(box,0,0,screen.width-1,0);
  158.     for (i = skip_it = 0 ; i < screen.height ; i++) /* scale file to screen */
  159.         {
  160.         if ((i % display_lines_per_buffer) == 0)
  161.             {           /* need another array */
  162.             if ((display_buffers[display_buffer_count] = (unsigned char *) malloc(DISPLAY_BUFFER_SIZE)) == NULL)
  163.                 {
  164.                 display_free();
  165.                 close_scaler();
  166.                 free(src_buffer);
  167.                 close(src_fh);
  168.                 fg_msm_showcursor();
  169.                 message_box("Out of memory.");
  170.                 return 0;
  171.                 }
  172.             p = display_buffers[display_buffer_count];
  173.             display_buffer_count++;
  174.             }
  175.         if (skip_it)
  176.             memset(p,0,scaler_out_bytes_per_line);
  177.         else if (!scaler(p))
  178.             skip_it = 1;
  179.         fg_drawmatrix(FG_BLACK,FG_MODE_SET,~0,FG_ROT0,screen.x